<?php

require_once 'vendor/autoload.php';

use Smalot\Cups\Builder\Builder;
use Smalot\Cups\Manager\JobManager;
use Smalot\Cups\Model\Job;
use Smalot\Cups\Model\Printer;
use Smalot\Cups\Transport\ResponseParser;
use Http\Client\Socket\Client as HttpClient;
use GuzzleHttp\Psr7\Request;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
 * 改进的IPP客户端 - 支持直接IP地址连接
 * 解决Host header和网络连接问题
 */
class ImprovedIPPClient
{
    private $ip;
    private $port;
    private $builder;
    private $httpClient;
    private $responseParser;
    private $jobManager;
    
    public function __construct($ip = '10.1.0.12', $port = 631)
    {
        $this->ip = $ip;
        $this->port = $port;
        $this->builder = new Builder();
        $this->httpClient = new HttpClient();
        $this->responseParser = new ResponseParser();
        $this->jobManager = new JobManager($this->builder, $this->httpClient, $this->responseParser);
    }
    
    /**
     * 测试网络连接
     */
    public function testConnection()
    {
        echo "🔍 测试网络连接到 {$this->ip}:{$this->port}\n";
        echo str_repeat('-', 40) . "\n";
        
        // 1. Ping测试
        echo "1. Ping测试...\n";
        $pingResult = $this->pingTest();
        
        if (!$pingResult) {
            echo "❌ Ping失败，无法继续\n";
            return false;
        }
        
        // 2. 端口连接测试
        echo "\n2. 端口连接测试...\n";
        $portResult = $this->portTest();
        
        // 3. HTTP连接测试
        echo "\n3. HTTP连接测试...\n";
        $httpResult = $this->httpTest();
        
        return $pingResult && ($portResult || $httpResult);
    }
    
    /**
     * Ping测试
     */
    private function pingTest()
    {
        $command = "ping -n 2 {$this->ip}";
        $output = [];
        exec($command, $output, $returnCode);
        
        foreach ($output as $line) {
            if (strpos($line, 'TTL=') !== false) {
                echo "✓ Ping成功: $line\n";
                return true;
            }
        }
        
        echo "❌ Ping失败\n";
        return false;
    }
    
    /**
     * 端口连接测试
     */
    private function portTest()
    {
        $connection = @fsockopen($this->ip, $this->port, $errno, $errstr, 5);
        
        if ($connection) {
            echo "✓ 端口{$this->port}连接成功\n";
            fclose($connection);
            return true;
        } else {
            echo "❌ 端口{$this->port}连接失败: $errstr ($errno)\n";
            return false;
        }
    }
    
    /**
     * HTTP连接测试
     */
    private function httpTest()
    {
        $connection = @fsockopen($this->ip, 80, $errno, $errstr, 5);
        
        if ($connection) {
            echo "✓ HTTP端口80连接成功\n";
            fclose($connection);
            
            // 尝试获取打印机信息
            $this->getPrinterInfo();
            return true;
        } else {
            echo "❌ HTTP端口80连接失败: $errstr ($errno)\n";
            return false;
        }
    }
    
    /**
     * 获取打印机信息
     */
    private function getPrinterInfo()
    {
        $url = "http://{$this->ip}/";
        $context = stream_context_create([
            'http' => [
                'timeout' => 5,
                'method' => 'GET',
                'header' => "User-Agent: CUPS-IPP-Client\r\n"
            ]
        ]);
        
        $response = @file_get_contents($url, false, $context);
        if ($response) {
            echo "✓ 打印机网页访问成功\n";
            
            if (stripos($response, 'epson') !== false) {
                echo "✓ 确认为EPSON打印机\n";
            }
            
            // 尝试提取打印机型号
            if (preg_match('/<title>([^<]+)</title>/i', $response, $matches)) {
                echo "  型号信息: " . trim($matches[1]) . "\n";
            }
        }
    }
    
    /**
     * 创建打印机对象
     */
    public function createPrinter($name = 'EPSON L4260 Series')
    {
        $printer = new Printer();
        $printer->setUri("ipp://{$this->ip}:{$this->port}/ipp/print");
        $printer->setName($name);
        
        echo "✓ 打印机对象创建完成\n";
        echo "  - URI: " . $printer->getUri() . "\n";
        echo "  - 名称: " . $printer->getName() . "\n";
        
        return $printer;
    }
    
    /**
     * 创建打印任务
     */
    public function createJob($name = 'IPP测试任务', $username = 'ipp-user')
    {
        $job = new Job();
        $job->setName($name);
        $job->setUsername($username);
        $job->setCopies(1);
        
        // 添加测试内容
        $content = $this->createTestContent();
        $job->addText($content);
        
        echo "✓ 打印任务创建完成\n";
        echo "  - 任务名称: " . $job->getName() . "\n";
        echo "  - 用户名: " . $job->getUsername() . "\n";
        
        return $job;
    }
    
    /**
     * 发送打印任务（改进版）
     */
    public function sendJob($printer, $job)
    {
        echo "\n🚀 发送打印任务...\n";
        echo "正在连接到 {$this->ip}:{$this->port}...\n";
        
        try {
            // 使用改进的HTTP客户端
            $result = $this->sendJobWithImprovedClient($printer, $job);
            
            if ($result) {
                echo "\n🎉 IPP打印任务发送成功！\n";
                echo "请检查打印机输出...\n";
                return true;
            } else {
                echo "\n❌ IPP打印任务发送失败\n";
                return false;
            }
            
        } catch (Exception $e) {
            echo "\n❌ IPP打印失败\n";
            echo "错误: " . $e->getMessage() . "\n";
            
            // 提供详细的错误分析
            $this->analyzeError($e);
            
            return false;
        }
    }
    
    /**
     * 使用改进的客户端发送任务
     */
    private function sendJobWithImprovedClient($printer, $job)
    {
        // 创建自定义HTTP客户端，设置正确的Host header
        $customClient = new class($this->ip, $this->port) extends HttpClient {
            private $targetIp;
            private $targetPort;
            
            public function __construct($ip, $port)
            {
                parent::__construct();
                $this->targetIp = $ip;
                $this->targetPort = $port;
            }
            
            public function sendRequest(RequestInterface $request): ResponseInterface
            {
                // 添加必要的headers
                $request = $request
                    ->withHeader('Host', $this->targetIp . ':' . $this->targetPort)
                    ->withHeader('User-Agent', 'CUPS-IPP-Client/1.0')
                    ->withHeader('Accept', 'application/ipp')
                    ->withHeader('Content-Type', 'application/ipp');
                
                // 修改URI以包含完整的目标地址
                $uri = $request->getUri()
                    ->withHost($this->targetIp)
                    ->withPort($this->targetPort)
                    ->withScheme('http');
                
                $request = $request->withUri($uri);
                
                return parent::sendRequest($request);
            }
        };
        
        // 使用自定义客户端创建JobManager
        $customJobManager = new JobManager($this->builder, $customClient, $this->responseParser);
        
        return $customJobManager->send($printer, $job);
    }
    
    /**
     * 错误分析
     */
    private function analyzeError($exception)
    {
        $message = $exception->getMessage();
        
        echo "\n🔧 错误分析:\n";
        
        if (strpos($message, 'Host header') !== false) {
            echo "- 问题：HTTP Host header缺失\n";
            echo "- 建议：使用Windows系统打印作为备用方案\n";
        }
        
        if (strpos($message, 'Connection refused') !== false) {
            echo "- 问题：连接被拒绝\n";
            echo "- 建议：检查打印机IPP服务是否启用\n";
        }
        
        if (strpos($message, 'timeout') !== false) {
            echo "- 问题：连接超时\n";
            echo "- 建议：检查网络连接和防火墙设置\n";
        }
        
        echo "\n💡 备用方案：\n";
        echo "1. 使用Windows系统打印\n";
        echo "2. 通过打印机网页界面打印\n";
        echo "3. 检查打印机IPP设置\n";
    }
    
    /**
     * Windows系统打印备用方案
     */
    public function windowsPrintFallback($content = null)
    {
        if (PHP_OS_FAMILY !== 'Windows') {
            echo "❌ 当前系统不是Windows\n";
            return false;
        }
        
        echo "\n🖥️  执行Windows系统打印...\n";
        
        $testFile = 'ipp_fallback_test.txt';
        $printContent = $content ?: $this->createTestContent();
        
        file_put_contents($testFile, $printContent);
        
        $printerNames = [
            'EPSON L4260 Series',
            'EPSON L4260',
            'L4260 Series'
        ];
        
        foreach ($printerNames as $printerName) {
            $command = "print /D:\"$printerName\" \"$testFile\"";
            
            $output = [];
            $returnCode = 0;
            exec($command . ' 2>&1', $output, $returnCode);
            
            if ($returnCode === 0) {
                echo "✅ Windows打印成功！\n";
                echo "打印机: $printerName\n";
                
                if (file_exists($testFile)) {
                    unlink($testFile);
                }
                
                return true;
            }
        }
        
        echo "❌ Windows打印也失败\n";
        
        if (file_exists($testFile)) {
            unlink($testFile);
        }
        
        return false;
    }
    
    /**
     * 创建测试内容
     */
    private function createTestContent()
    {
        $content = "";
        $content .= str_repeat('=', 50) . "\n";
        $content .= "    改进的IPP客户端打印测试\n";
        $content .= "      EPSON L4260 Series\n";
        $content .= str_repeat('=', 50) . "\n\n";
        
        $content .= "连接信息:\n";
        $content .= "- IP地址: {$this->ip}\n";
        $content .= "- 端口: {$this->port}\n";
        $content .= "- 协议: IPP (Internet Printing Protocol)\n";
        $content .= "- 时间: " . date('Y-m-d H:i:s') . "\n";
        $content .= "- PHP版本: " . PHP_VERSION . "\n\n";
        
        $content .= "功能测试:\n";
        $content .= "✓ 网络连接正常\n";
        $content .= "✓ IPP协议通信\n";
        $content .= "✓ 任务创建成功\n";
        $content .= "✓ 内容传输完成\n";
        $content .= "✓ 中文字符支持: 改进的网络打印测试\n\n";
        
        $content .= "技术改进:\n";
        $content .= "✓ 修复了Host header问题\n";
        $content .= "✓ 增强了错误处理\n";
        $content .= "✓ 提供了备用打印方案\n";
        $content .= "✓ 改进了网络连接检测\n\n";
        
        $content .= "如果您能看到这个测试页面，\n";
        $content .= "说明改进的IPP客户端工作正常！\n\n";
        
        $content .= str_repeat('-', 50) . "\n";
        $content .= "测试完成: " . date('Y-m-d H:i:s') . "\n";
        $content .= "客户端版本: ImprovedIPPClient v1.0\n";
        
        return $content;
    }
    
    /**
     * 完整的打印测试流程
     */
    public function runFullTest()
    {
        echo "🖨️  改进的IPP客户端 - 完整测试\n";
        echo "目标打印机: {$this->ip}:{$this->port}\n";
        echo str_repeat('=', 60) . "\n\n";
        
        // 1. 网络连接测试
        if (!$this->testConnection()) {
            echo "\n❌ 网络连接失败，无法继续IPP测试\n";
            echo "尝试Windows系统打印...\n";
            return $this->windowsPrintFallback();
        }
        
        // 2. 创建打印机和任务
        echo "\n📝 创建打印对象...\n";
        $printer = $this->createPrinter();
        $job = $this->createJob();
        
        // 3. 发送打印任务
        $success = $this->sendJob($printer, $job);
        
        // 4. 如果IPP失败，尝试Windows打印
        if (!$success) {
            echo "\n🔄 IPP打印失败，尝试Windows系统打印...\n";
            $success = $this->windowsPrintFallback();
        }
        
        echo "\n" . str_repeat('=', 60) . "\n";
        
        if ($success) {
            echo "✅ 打印测试完成！请检查打印机输出。\n";
        } else {
            echo "❌ 所有打印方式都失败。请检查打印机状态。\n";
        }
        
        return $success;
    }
}

// 如果直接运行此文件，执行测试
if (basename(__FILE__) === basename($_SERVER['SCRIPT_NAME'])) {
    echo "启动改进的IPP客户端测试...\n\n";
    
    $client = new ImprovedIPPClient('10.1.0.12', 631);
    $client->runFullTest();
}